﻿using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;

namespace CO2FixCalibration
{
    class SimulateCO2Fix
    {
        static int MaxTime = 10000;

        [DllImport("User32")]
        private static extern int ShowWindow(int hwnd, int nCmdShow);

        [DllImport("user32.dll")]
        static extern bool SetCursorPos(int X, int Y);

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);

        private const int MOUSEEVENTF_LEFTDOWN = 0x02;
        private const int MOUSEEVENTF_LEFTUP = 0x04;
        private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
        private const int MOUSEEVENTF_RIGHTUP = 0x10;

        private const int SW_MAXIMIZE = 3;

        static System.Drawing.Point OpenFilePosition = new System.Drawing.Point(40, 50);
        static System.Drawing.Point ExportPosition = new System.Drawing.Point(90, 50);

        static Process CO2FixProcess = null;
        private static WINDOWPLACEMENT GetPlacement(IntPtr hwnd)
        {
            WINDOWPLACEMENT placement = new WINDOWPLACEMENT();
            placement.length = Marshal.SizeOf(placement);
            GetWindowPlacement(hwnd, ref placement);
            return placement;
        }

        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool GetWindowPlacement(
            IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);

        [Serializable]
        [StructLayout(LayoutKind.Sequential)]
        internal struct WINDOWPLACEMENT
        {
            public int length;
            public int flags;
            public ShowWindowCommands showCmd;
            public System.Drawing.Point ptMinPosition;
            public System.Drawing.Point ptMaxPosition;
            public System.Drawing.Rectangle rcNormalPosition;
        }

        internal enum ShowWindowCommands : int
        {
            Hide = 0,
            Normal = 1,
            Minimized = 2,
            Maximized = 3,
        }
        private static void LeftMouseClick(System.Drawing.Point p)
        {
            SetCursorPos(p.X, p.Y);
            mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
            Thread.Sleep(500);
            mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
            Thread.Sleep(500);
        }
        private static void Enter(string text)
        {
            Thread.Sleep(500);
            SendKeys.SendWait(text);
            Thread.Sleep(100);
            SendKeys.SendWait("{ENTER}");
        }
        
        public static bool IsRunning()
        { 
            Process[] processlist = Process.GetProcesses();

            foreach(Process theprocess in processlist)
            {
                if (theprocess.ProcessName == "CO2Fix") return true;
            }
            return false;
        }
        public static void StartCO2Fix()
        {
            
            do
            {
                ProcessStartInfo startInfo = new ProcessStartInfo();
                startInfo.FileName = "C:\\Program Files (x86)\\CO2Fix 3.2\\CO2Fix.exe";
                CO2FixProcess = Process.Start(startInfo);

            }
            while (!IsRunning());
        }
        public static void MaximizeCO2Fix()
        {

            Thread.Sleep(500);
            int hWnd = CO2FixProcess.MainWindowHandle.ToInt32();
            ShowWindow(hWnd, SW_MAXIMIZE);

            var placement = GetPlacement(CO2FixProcess.MainWindowHandle);
            if (placement.showCmd != ShowWindowCommands.Maximized) MaximizeCO2Fix();
             
            
        }
        public static void KillCo2Fix()
        {

            while (IsRunning())
            {
                Process[] processlist = Process.GetProcesses();
                foreach (Process theprocess in processlist)
                {
                    if (theprocess.ProcessName == "CO2Fix")
                    {
                        if (theprocess.HasExited == false)
                        {
                            theprocess.Kill();
                        }
                    }
                }
            
            }

        }
        public static bool Run(string CO2FixFileName, string ExportFileName, out string msg)
        {
            msg = "ok";
            bool success = false;
            int NrOfTries = 0;
            do
            {
                var MyThread = new Thread(() => success = Execute(CO2FixFileName, ExportFileName));
                MyThread.Start();

                if (MyThread.Join(MaxTime) == false)
                {
                    success = false;
                    KillCo2Fix();
                    NrOfTries++;
                    if (NrOfTries > 25)
                    {
                        msg = "Unable to run " + CO2FixFileName;
                        break;
                    }
                }
                if (!success)
                {
                    MaxTime = (int)(1.1 * (double)MaxTime);
                }

                 
            }
            while (!success);

            return true;
        
        }
        public static bool ExportFileSuccess(string ExportFileName)
        {
            if (System.IO.File.Exists(ExportFileName) == false) return false;
            string[] Content =  System.IO.File.ReadAllLines(ExportFileName);
            string lastline = Content[Content.Length - 1];
            if(lastline.Split((char[])null, StringSplitOptions.RemoveEmptyEntries)[0].Trim() != "300") return false;
            return true;
              
        }
        public static bool Execute(string CO2FixFileName, string ExportFileName)
        {


            try
            {
                StartCO2Fix();

                MaximizeCO2Fix();

                LeftMouseClick(OpenFilePosition);

                Enter(CO2FixFileName);
                Thread.Sleep(500);

                LeftMouseClick(ExportPosition);

                Enter(ExportFileName);
                Thread.Sleep(100);

                KillCo2Fix();

                return ExportFileSuccess(ExportFileName);
            }
            catch 
            {
                return false;
            }
        }
    }
}
